package mymyoux.io
{
	import flash.errors.IOError;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.Socket;
	import flash.utils.ByteArray;
	
	import mymyoux.debug.Log;
	import mymyoux.io.mserveur.mapping.PyGram;

	public class Socket
	{
		public namespace binary = "binary";
		public namespace text = "text";
		public namespace normal = "normal";
		public static const MIN_PORT:uint = 1024;
		public static const MAX_PORT:uint = 65535;
		protected var _socket:flash.net.Socket;
		protected var _namespace:Namespace;
		
		public function Socket(socket:flash.net.Socket = null)
		{
			_namespace = normal; 
			this.socket = socket;
		}
		public function get socket():flash.net.Socket
		{
			return _socket;
		}
		public function set socket(value:flash.net.Socket):void
		{
			if(_socket != null)
			{
				close();
				_socket.removeEventListener(Event.CLOSE,onClose);
				_socket.removeEventListener(Event.CONNECT,onConnect);
				_socket.removeEventListener(IOErrorEvent.IO_ERROR,onError);
				_socket.removeEventListener(SecurityErrorEvent.SECURITY_ERROR,onError);
				_socket.removeEventListener(ProgressEvent.SOCKET_DATA,onData);
			}
			_socket = value;
			if(_socket != null)
			{
				_socket.addEventListener(Event.CLOSE,onClose);
				_socket.addEventListener(Event.CONNECT,onConnect);
				_socket.addEventListener(IOErrorEvent.IO_ERROR,onError);
				_socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onError);
				_socket.addEventListener(ProgressEvent.SOCKET_DATA,onData);
			}
		}
		public function close():void
		{
			try
			{
				if(_socket != null)
				{
					_socket.flush();
					_socket.close();
					_namespace = null;
				}
			}catch(error:IOError)
			{
				Log.error(error);
			}
		}
		public function createSocket(ip:String, port:uint):void
		{
			if(port >= MIN_PORT && port <= MAX_PORT)
			{
				this.socket = new flash.net.Socket();
				this.socket.connect(ip,port);
			}		
		}		
		protected function onData(event:ProgressEvent):void
		{
			Log.debug("ssocket:"+event);
			 _namespace::readData();
		}
		normal function readData():void
		{
			while(socket.bytesAvailable>0)
			{
				try
				{
					var b:ByteArray = new ByteArray();
					socket.readBytes(b,0,socket.bytesAvailable);
					try
					{
						var object:Object = b.readObject();
						_namespace = binary;
						Log.trace("mode = binary");
					}catch(berror:Error)
					{
						b.position = 0;
						var data:String = b.readUTFBytes(b.length);
						_namespace = text;
						Log.trace("mode = text");
						_namespace::processData(data);
					}
				}catch(error:Error)
				{
					Log.trace("read error : " + error);
				}
			}
		}
		binary function readData():void
		{
			while(socket.bytesAvailable>0)
			{
				try
				{
					Log.trace(socket.readObject());
				}catch(error:Error)
				{
					Log.trace("read binary error : "+error);
				}
			}
		}
		binary function processData(data:Object):void
		{
			
		}
		text function readData():void
		{
			while(socket.bytesAvailable>0)
			{
				try
				{
					_namespace::processData(socket.readUTFBytes(socket.bytesAvailable));
				}catch(error:Error)
				{
					Log.trace("read text error : " + error);
				}
			}
		}
		text function processData(data:String):void
		{
			//[action:type(/delimiter)=parameters]
			if(data.substring(data.length-2)=="\r\n")
			{
				data = data.substring(0,data.length-2);
			}
			var index:int = data.indexOf(":");
			var read:Boolean = false;
			if(index > -1)
			{
				var msg:PyGram = new PyGram();
				msg.action = data.substring(1,index);
				var index2:int = data.indexOf("=");
				if(index2 > -1)
				{
					var type:String = data.substring(index + 1, index2).toLowerCase();
					var value:Array = new Array();
					value.push(data.substring(index2 + 1,data.length - 1));
					index = type.indexOf("/");
					if(index > -1)
					{
						var dmr:String;
						dmr = type.substring(index +1);
						type = type.substring(0,index);
						if(dmr.length>0)
						{
							value = value[0].split(dmr);
						}
					}
					read = true;
					var i:int = 0;
					var length:int = value.length;
					switch(type)
					{
						case "string":
							for(; i<length; i++)
							{
								msg.parameters.push(value[i]);
							}
						break;
						case "int":
							for(; i<length; i++)
							{
								msg.parameters.push(int(new Number(value[i])));
							}
						break;
						case "uint":
							for(; i<length; i++)
							{
								msg.parameters.push(uint(new Number(value[i])));
							}
						case "number":
							for(; i<length; i++)
							{
								msg.parameters.push(new Number(value[i]));
							}
						break;
						case "boolean":
							for(; i<length; i++)
							{
								msg.parameters.push(value[i]=="true");
							}
						break;
						default:
						Log.error("undetermined type : "+type);
						Log.error(value);
						read = false;
					}
				}
			}
			if(!read)
			{
				Log.warn("unread msg : "+data);
			}else
			{
				Log.trace(msg);
			}
		}
		public function send(data:Object):void
		{
			//_namespace::sendData(data);
		}
		normal function sendData(data:Object):void
		{
			binary::sendData(data);
		}
		text function sendData(data:Object):void
		{
			socket.writeUTFBytes(data.toString());
		}
		binary function sendData(data:Object):void
		{
			socket.writeObject(data);
		}
		protected function onError(event:Event):void
		{
			Log.debug(event);
		}
		protected function onClose(event:Event):void
		{
			Log.debug(event);
		}
		protected function onConnect(event:Event):void
		{
			Log.debug(event);
		}

	}
}